#ifndef SIMPLE_DYNAMIC_ARRAY
#define SIMPLE_DYNAMIC_ARRAY

/**
 * \brief Simple dynamic array based on the c-style static array
 * \note All memory in stack, this is the first stratege
 * \tparam T the type of the contained object
 * */
template <class T>
class DynamicArr {
public:
  using value_type = T;
  using reference_type = T &;
  using pointer_type = T *;
  using const_reference_type = const T &;
  using const_pointer_type = const T *;
  using size_type = unsigned long long;

  DynamicArr( size_type capacity ) : _capacity( capacity ), _size(0) {
    if ( _heap_mem_ ) delete[] _heap_mem_;
    _heap_mem_ = new T[_capacity];
  }

  DynamicArr() : _capacity( DEFAULT_CAPACITY ), _size(0) {}

  // add element to this end of this array
  void addToEnd( const_reference_type o );

  // get size form this array
  size_type size() const { return _size; }

  reference_type get( size_type i ) noexcept { return _heap_mem_[i]; }
  const_reference_type get( size_type i ) const { return _heap_mem_[i]; }

  bool empty() const { return _size == 0; }

  // clear all data in this array
  void reset() { _size = 0; }

  ~DynamicArr() {
    if ( _heap_mem_ ) delete[] _heap_mem_;
    _heap_mem_ = nullptr;
  }

private:
  const size_type DEFAULT_CAPACITY = 32;

  // expand the capacity of this array
  void expand();

  // exact capacity in this array
  size_type _capacity;
  // exact size in this array element
  size_type _size;

  // TODO: may be this is a static member
  pointer_type _heap_mem_ = nullptr;


  // cached mem
  // const size_type MAX_CACHE_CAPACITY = 100;
  // value_type _cache_mem_[MAX_CACHE_CAPACITY];
};

#endif